package fr.babos.test.perfs 
{
	import com.greensock.easing.Back;
	import com.greensock.TweenMax;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.PixelSnapping;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.ImageDecodingPolicy;
	import flash.system.LoaderContext;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
	import flash.utils.Dictionary;
	import fr.babos.touch.emulator.MouseToTouchEmulator;
	import net.hires.debug.Stats;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class PerfsTest extends Sprite 
	{
		protected var _twitterData:Object;
		
		protected var _imagesURLs		:Vector.<String> 			= new Vector.<String>;
		protected var _imagesData		:Vector.<BitmapData> 		= new Vector.<BitmapData>;
		protected var _images			:Vector.<DisplayObject> 	= new Vector.<DisplayObject>;
		
		protected var _directions		:Dictionary					= new Dictionary();
		
		public function PerfsTest() 
		{
			if (stage == null)
				addEventListener(Event.ADDED_TO_STAGE, init);
			else
				init();
		}
		
		private function init (e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			stage.frameRate = 60;
			
			stage.quality = StageQuality.LOW;
			
			addChild(new Stats());
			
			if (Multitouch.supportsTouchEvents)
			{
				Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
			}
			else
			{
				MouseToTouchEmulator.emulate(stage, true, true, false);
			}
			
			
			//var serviceURL:String = "http://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=zouloux&count=100";
			var serviceURL:String = "http://search.twitter.com/search.json?q=flash&rpp=300&include_entities=true&result_type=mixed";
			
			var urlLoader:URLLoader = new URLLoader(new URLRequest(serviceURL));
			urlLoader.addEventListener(Event.COMPLETE, dataLoadedHandler);
			trace("loading");
		}
		
		public function dataLoadedHandler (event:Event):void
		{
			(event.currentTarget as URLLoader).removeEventListener(Event.COMPLETE, dataLoadedHandler);
			
			trace("loaded");
			
			_twitterData = JSON.parse((event.currentTarget as URLLoader).data);
			
			if (_twitterData["results"] != null)
				_twitterData = _twitterData.results;
			
			const total:uint = _twitterData.length;
			
			for (var i:uint = 0; i < total; i ++)
			{
				var imageURL:String;
				
				if (_twitterData[i].profile_image_url != null)
					imageURL = _twitterData[i].profile_image_url;
				else if (_twitterData[i].user != null)
					imageURL = _twitterData[i].user.profile_image_url;
				
				//trace(imageURL);
				
				_imagesURLs.push(imageURL);
			}
			
			// Commencer par charger la première image
			loadImage();
			loadImage();
			loadImage();
			
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
		
		protected function loadImage ():void
		{
			if (_imagesURLs.length > 0)
			{
				var loader:Loader = new Loader();
				var context:LoaderContext = new LoaderContext();
				context.allowCodeImport = false;
				context.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
				
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadedHandler);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.DISK_ERROR, errorHandler);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.NETWORK_ERROR, errorHandler);
				loader.contentLoaderInfo.addEventListener(IOErrorEvent.VERIFY_ERROR, errorHandler);
				
				loader.load(new URLRequest(_imagesURLs.shift()), context);
			}
		}
		
		protected function errorHandler (event:IOErrorEvent):void
		{
			//trace(event.text);
			
			loadImage();
		}
		
		protected function imageLoadedHandler (event:Event):void
		{
			//trace("image loaded");
			
			var bitmapData:BitmapData = ((event.currentTarget as LoaderInfo).content as Bitmap).bitmapData;
			
			_imagesData.push(bitmapData);
			
			createImage(bitmapData);
			
			loadImage();
		}
		
		/*
		// 30 FPS
		private function createImage (bitmapData:BitmapData):void 
		{
			var shape:Shape = new Shape();
			
			var point1:Point = new Point(0, 0);
			var point2:Point = new Point(bitmapData.width, 0);
			var point3:Point = new Point(0, bitmapData.height);
			var point4:Point = new Point(bitmapData.width, bitmapData.height);
			
			var uvPoint1:Point = new Point(0, 0);
			var uvPoint2:Point = new Point(1, 0);
			var uvPoint3:Point = new Point(0, 1);
			var uvPoint4:Point = new Point(1, 1);
			
			var verticies:Vector.<Number> = Vector.<Number>([point1.x, point1.y, point2.x, point2.y, point3.x, point3.y, point4.x, point4.y]);
			var indices:Vector.<int> = Vector.<int>([0, 1, 2, 1, 3, 2]);
			var uvtData:Vector.<Number> = Vector.<Number>([uvPoint1.x, uvPoint1.y, uvPoint2.x, uvPoint2.y, uvPoint3.x, uvPoint3.y, uvPoint4.x, uvPoint4.y]);
			
			shape.graphics.beginBitmapFill(bitmapData, new Matrix(), false, true);
			shape.graphics.drawTriangles(verticies, indices, uvtData);
			shape.graphics.endFill();
			
			//shape.cacheAsBitmap = true;
			//shape.cacheAsBitmapMatrix = new Matrix();
			
			place(shape);
		}
		*/
		
		/*
		// 28 FPS
		private function createImage (bitmapData:BitmapData):void 
		{
			var shape:Shape = new Shape();
			
			shape.graphics.beginBitmapFill(bitmapData, new Matrix(), false, true);
			shape.graphics.drawRect(0, 0, bitmapData.width, bitmapData.height);
			shape.graphics.endFill();
			
			//shape.cacheAsBitmap = true;
			//shape.cacheAsBitmapMatrix = new Matrix();
			
			place(shape);
		}
		*/
		
		
		
		// 35 FPS
		private function createImage (bitmapData:BitmapData):void 
		{
			//var bitmap:Bitmap = new Bitmap(bitmapData, PixelSnapping.NEVER, true);
			
			// + 1 FPS (no smooth)
			var bitmap:Bitmap = new Bitmap(bitmapData, PixelSnapping.NEVER, false);
			
			// -10 FPS :-/
			//bitmap.opaqueBackground = true;
			
			// -2 FPS
			//bitmap.cacheAsBitmap = true;
			//bitmap.cacheAsBitmapMatrix = new Matrix();
			
			// -20 FPS !
			//bitmap.z = 0;
			
			place(bitmap);
		}
		
		private function place (pDisplayObject:DisplayObject):void
		{
			_images.push(pDisplayObject);
			
			_directions[pDisplayObject] = {
				x: Math.random() * 2 - 1,
				y: Math.random() * 2 - 1,
				rotation: Math.random() * 6 - 3
			};
			
			pDisplayObject.scaleX = pDisplayObject.scaleY = 1 + Math.random();
			
			pDisplayObject.x = (stage.stageWidth - pDisplayObject.width) * Math.random();
			pDisplayObject.y = (stage.stageHeight - pDisplayObject.height) * Math.random();
			
			TweenMax.from(pDisplayObject, .5, {
				alpha: 0
			});
			TweenMax.from(pDisplayObject, .7, {
				scaleX: 0,
				scaleY: 0,
				ease: Back.easeOut
			});
			
			addChildAt(pDisplayObject, 0);
		}
		
		protected function enterFrameHandler (event:Event):void 
		{
			var total:uint = _images.length;
			var image:DisplayObject;
			
			for (var i:int = 0; i < total; i++) 
			{
				image = _images[i];
				
				if (image.x < 0)
					_directions[image].x = Math.abs(_directions[image].x);
				else if (image.x > stage.stageWidth - image.width)
					_directions[image].x = - Math.abs(_directions[image].x);
					
				if (image.y < 0)
					_directions[image].y = Math.abs(_directions[image].y);
				else if (image.y > stage.stageHeight - image.height)
					_directions[image].y = - Math.abs(_directions[image].y);
				
				_images[i].x += _directions[image].x;
				_images[i].y += _directions[image].y;
				//_images[i].rotation += _directions[image].rotation;
			}
		}
	}
}